#include "front/front_interface.h"

using namespace ppspeech;


bool FrontEngineInterface::FrontGetSentencePhoneme(const string& fpInSentence, vector< vector<string> >* fpOutPhonemes)
{
	vector<pair<string, string>> tCutResult;	//分词结果包含词和词性

	if( ! FrontCutSentenceWords(fpInSentence, tCutResult)) {
		cout << "ERROR: Frontend: 切句失败: " << fpInSentence << endl;
		return false;
	}

	if( ! FrontGetCutWordsIds(tCutResult, fpOutPhonemes) ) {
		cout << "ERROR: Frontend: 获取切词音素失败!" << endl;
		return false;
	}
	return true;
}


bool FrontEngineInterface::FrontCutSentenceWords(const string& fpInSentence, vector<pair<string, string>>& cut_result)
{
	vector<pair<string, string>> tJiebaCutResult;

	// 结巴分词
	mFrontJieba->Tag(fpInSentence, tJiebaCutResult);

	// 对分词后结果进行整合
	if (0 != MergeforModify(tJiebaCutResult, cut_result)) {
		cout << "ERROR: Frontend: 分词整合失败！" << endl;
		return false;
	}

	return true;
}


bool FrontEngineInterface::FrontGetCutWordsIds(const vector<pair<string, string>>& fpInCutResult, vector< vector<string> >* fpOutPhonemes)
{
	vector<string> fpOutPhoneme;
	vector<int64_t> fpOutPhoneids;
	vector< pair<string, LanguageEnum> > tVecPhonemeResult;

	for (int i = 0; i < fpInCutResult.size(); i++) {
		const string tcCurrWord = fpInCutResult[i].first;
		const string tcCurrPos = fpInCutResult[i].second;

		cout << tcCurrWord << endl;

		if( find(_punc_omit.begin(), _punc_omit.end(), tcCurrWord) == _punc_omit.end() )	//非可忽略的标点
		{
			vector<string> tWordInitials = {};
			vector<string> tWordFinals = {};
			pair<string, LanguageEnum> tPhonemeResult = {"", LANG_ZH};
			
			// 判断是否在标点符号集合中
			if (find(mcPunctuation.begin(), mcPunctuation.end(), tcCurrWord) == mcPunctuation.end())	//文字
			{
				string tCurrWord = tcCurrWord;

				StrReplace(tCurrWord, " ", "");
				if(tCurrWord.length() == 0)
				{
					continue;
				}

				const wstring tcWstrCurrWord = utf8string2wstring(tCurrWord);	//根据word的首字节判断是不是英文单词或希腊字母
				const wchar_t tcWcharFirst = tcWstrCurrWord.at(0);
				
				if((tcWcharFirst >= L'Α' && tcWcharFirst <= L'Ω' || tcWcharFirst == L'∧' || tcWcharFirst == L'∑' || tcWcharFirst == L'∏')
					 || (tcWcharFirst >= L'α' && tcWcharFirst <= L'ω'))	//word是希腊字母
				{
					tPhonemeResult.second = LANG_EN;
					string tEnPhonemeTemp = "";
					//直接查询英文热词词典。tcWstrCurrWord
					if( "" != (tEnPhonemeTemp = mDictionaryBias.find_sqlite_dict(DatabaseDictTableEnWord, tCurrWord) ) )
					{
						tPhonemeResult.first = tEnPhonemeTemp;
					}
					else {
						tPhonemeResult.first = "sp";
					}
				}
				else if(i > 0 && tCurrWord == "'s")
				{
					tPhonemeResult.second = LANG_EN;
					//名词所有格's 的读音与名词复数和动词第三人称单数相同
					//在清辅音后读 [s]，如 cat's [kæts]，cock's  [kɔks]
					//浊辅音和元音后读 [z]，如 dog's [dɔgz]，doctor's ['dɔktəz]
					//摩擦音 s、x、ch 和 sh 后读 [ɪz]，如 fox's ['fɔksɪz]，fish's ['fɪʃz]
					vector<string> tLastPhonemeSplit;
					if(tVecPhonemeResult.size() > 0  &&  tVecPhonemeResult.back().second == LANG_EN) {	
						tLastPhonemeSplit = StrSplit(tVecPhonemeResult.back().first, " ");
					}
					cout << "上个词音素切分：" << tLastPhonemeSplit << endl;
					if(tLastPhonemeSplit.size() > 0) {
						const string tLastWord = fpInCutResult[i-1].first;
						const size_t tLastWordLength = tLastWord.length();
						const string tLastPhoneme = tLastPhonemeSplit[tLastPhonemeSplit.size() - 1];
						cout << "]]]" << tLastWord << "]]]" << tLastPhoneme << endl;
						
						//摩擦音
						if(tLastPhoneme=="S" || tLastPhoneme=="CH" || tLastPhoneme=="SH") {
							tPhonemeResult.first = "IH0 Z";
						}
						//清辅音
						else if(tLastPhoneme=="P" || tLastPhoneme=="T" || tLastPhoneme=="K" || tLastPhoneme=="F" || 
							tLastPhoneme=="TH" || tLastPhoneme=="HH" || tLastPhoneme=="M" || tLastPhoneme=="N" || tLastPhoneme=="NG" 
						) {
							tPhonemeResult.first = "S";
						}

						else if(  tLastWordLength >= 2  &&  ("ch" == tLastWord.substr(tLastWordLength-2) || "sh" == tLastWord.substr(tLastWordLength-2) )  ) {
							tPhonemeResult.first = "IH0 Z";
						}
						else if(  tLastWordLength >= 1  &&  ("s" == tLastWord.substr(tLastWordLength-1) || "x" == tLastWord.substr(tLastWordLength-1) )  ) {
							tPhonemeResult.first = "IH0 Z";
						}

						else {
							tPhonemeResult.first = "Z";
						}
					}
					else {
						tPhonemeResult.first = "Z";
					}
				}
				else if((tcWcharFirst >= L'a' && tcWcharFirst <= L'z') || (tcWcharFirst >= L'A' && tcWcharFirst <= L'Z'))	//word是英文
				{
					tPhonemeResult.second = LANG_EN;
					cout << tCurrWord << endl;
					string tLower = tCurrWord;
					string tEnPhonemeTemp = "";

					transform(tLower.begin(), tLower.end(), tLower.begin(), ::tolower);		//大写转小写

					//英文单字查询。如果热词词典找不到，则找常规词典。
					if( "" != (tEnPhonemeTemp = mDictionaryBias.find_sqlite_dict(DatabaseDictTableEnWord, tLower) )
						 || "" != (tEnPhonemeTemp = mDictionary.find_sqlite_dict(DatabaseDictTableEnWord, tLower) ) )
					{
						tPhonemeResult.first = tEnPhonemeTemp;
					}
					else {
						for(const char tLetter: tLower) {		//单词拆解成字母
							if(tLetter >= 'a' && tLetter <= 'z') {
								tEnPhonemeTemp += mcLetterPhoneme[tLetter-'a'] + " ";
							}
						}
						if(tEnPhonemeTemp != "" && tEnPhonemeTemp[tEnPhonemeTemp.length()-1] == ' ') {
							tEnPhonemeTemp = tEnPhonemeTemp.substr(0, tEnPhonemeTemp.length()-1);
						}
						else if(tEnPhonemeTemp == ""){
							tEnPhonemeTemp = "sp";
						}

						tPhonemeResult.first = tEnPhonemeTemp;
					}
				}
				else if(tCurrWord == "`a~") {
					tPhonemeResult.second = LANG_EN;
					tPhonemeResult.first = "ER0";
				}
				else
				{
					tPhonemeResult.second = LANG_ZH;
					StrReplace(tCurrWord, " ", "");

					// 获取字词的声母韵母列表
					if (0 != GetInitialsFinals(tCurrWord, &tWordInitials, &tWordFinals)) {
						cout << "ERROR: Frontend: 词组的声母韵母获取失败！" << tCurrWord << endl;
						return false;
					}

					cout << tcCurrWord << tWordInitials << tWordFinals << endl;
					
					if(tWordFinals.size() == 0)			//避免出现无音素的情况
					{
						tPhonemeResult.first = "sp";	// fastspeech2
					}
					else
					{
						// 对读音进行修改
						if( false == FrontModifyTone(tCurrWord, tcCurrPos, tWordFinals) ) {
							cout << "ERROR: Frontend: 更改音调失败！" << endl;
						}

						// 对儿化音进行修改
						vector< vector<string> > new_initals_finals = MergeErhua(tWordInitials, tWordFinals, tCurrWord, tcCurrPos);
						tWordInitials = new_initals_finals[0];
						tWordFinals = new_initals_finals[1];

						// 将声母和韵母合并成音素
						assert(tWordInitials.size() == tWordFinals.size());
						string temp_phone;
						for (int j = 0; j < tWordInitials.size(); j++) {
							temp_phone = tWordInitials[j] + tWordFinals[j];

							if (j == 0) {
								tPhonemeResult.first += temp_phone;
							} else {
								tPhonemeResult.first += ("_" + temp_phone);
							}
						}
					}
				}
			}
			else {  // 标点符号
				tPhonemeResult.second;			//保持语言

				if(tcCurrWord == "。" || tcCurrWord == "？") {
					tPhonemeResult.first = "#4";
				}
				else {
					tPhonemeResult.first = "#3";
				}
			}

			cout << "INFO：Frontend：音素：" << tPhonemeResult << "|" << endl;

			tVecPhonemeResult.push_back(tPhonemeResult);
		}
	}

	cout << tVecPhonemeResult << endl;

	for(size_t i=0; i<tVecPhonemeResult.size(); i++) {
		string tCurrPhoneme = tVecPhonemeResult[i].first;
		string tNextPhoneme = (i+1<tVecPhonemeResult.size()) ? tVecPhonemeResult[i+1].first : "";
		const vector<string> tcCurrVec = absl::StrSplit(tCurrPhoneme, " ");
		const vector<string> tcNextVec = absl::StrSplit(tNextPhoneme, " ");

		//当前词尾部为第三声，下个词头部为第三声，上个词尾部的音调进行修改为第二声
		const bool tcbCurrBackTone3 = ( tcCurrVec.size()>0 && absl::EndsWith(tcCurrVec.back(),"3") );
		const bool tcbNextFrontTone3 = ( tcNextVec.size()>0 && absl::EndsWith(tcNextVec[0],"3") ) || ( tcNextVec.size()>1 && absl::EndsWith(tcNextVec[1],"3") );
		/*if(tcbCurrBackTone3 && tcbNextFrontTone3) {
			tCurrPhoneme = tCurrPhoneme.substr(0, tCurrPhoneme.length()-1) + "2";
		}*/

		// 音素到音素id

		const string tcAliSpeakerName = "F7";
		const string tcAliEmotionNone = "emotion_none";
		const string tcAliEmotionNautral = "emotion_neutral";
		const string tcAliWordNone = "word_none";
		const string tcAliWordBegin = "word_begin";
		const string tcAliWordMiddle = "word_middle";
		const string tcAliWordEnd = "word_end";
		const string tcAliSubNone = "s_none";
		const string tcAliSubBegin = "s_begin";
		const string tcAliSubEnd = "s_end";
		const string tcAliToneNone = "tone_none";

		if(tCurrPhoneme.length() > 0 && tCurrPhoneme.at(0)=='#') {	//停顿符号
			if(fpOutPhonemes->size() > 0  &&  fpOutPhonemes->back().size() > 0
				  &&  fpOutPhonemes->back()[0].length() > 0  &&  fpOutPhonemes->back()[0][0]=='#')
			{
				fpOutPhonemes->pop_back();
			}
			fpOutPhonemes->push_back(vector<string> {tCurrPhoneme, tcAliToneNone, tcAliSubNone, tcAliWordNone, tcAliEmotionNone, tcAliSpeakerName} );
		}
		else {
			const vector<string> tcvSplitWord = StrSplit(tCurrPhoneme, "_");
			const size_t tcSplitNum = tcvSplitWord.size();
			for(size_t i=0; i<tcSplitNum; i++) {
				string tToneIndex = "0";
				if(tcvSplitWord[i].length() > 0) {
					tToneIndex = tcvSplitWord[i].at(tcvSplitWord[i].length()-1);
					if(tToneIndex[0] < '1' || tToneIndex[0] > '5') {
						continue;
					}
				}

				string tPinyin = tcvSplitWord[i].substr(0, tcvSplitWord[i].length()-1);
				auto tPinyinIterator = mPhonemeIndexMap.find(tPinyin);
				if(tPinyinIterator == mPhonemeIndexMap.end()) {
                    std::cout<<"pinyin "<<tPinyin<<std::endl;
					continue;
				}

				fpOutPhonemes->push_back(vector<string> {tPinyinIterator->second.first, "tone"+tToneIndex, tcAliSubBegin, (i==0?tcAliWordBegin:tcAliWordMiddle), tcAliEmotionNautral, tcAliSpeakerName} );
				fpOutPhonemes->push_back(vector<string> {tPinyinIterator->second.second, "tone"+tToneIndex, tcAliSubEnd, (i==tcSplitNum-1?tcAliWordEnd:tcAliWordMiddle), tcAliEmotionNautral, tcAliSpeakerName} );
			}

			fpOutPhonemes->push_back(vector<string> {"#1", tcAliToneNone, tcAliSubNone, tcAliWordNone, tcAliEmotionNone, tcAliSpeakerName} );
		}
	}

	return true;
}
